home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / manageme / tcpdump-.7 / tcpdump- / tcpdump-richard-1.7 / libpcap-0.0 / pcap-linux.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-24  |  4.9 KB  |  211 lines

  1. /*
  2.  * Linux interface for packet capture lib ported by Adam Caldwell
  3.  * (acaldwel@ace.cs.ohiou.edu). Based on the pcap-snoop.c file. 
  4.  * May be freely redistributed as per the GNU license
  5.  */
  6. #include <sys/param.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <netdb.h>
  10. #include <ctype.h>
  11. #include <signal.h>
  12. #include <errno.h>
  13. #include <sys/time.h>
  14. #include <sys/socket.h>
  15. #include <sys/file.h>
  16. #include <sys/ioctl.h>
  17. #include <malloc.h>
  18. #include <memory.h>
  19. #include <unistd.h>
  20.  
  21.  
  22. #include <net/if.h>
  23. #include <net/if_arp.h>
  24. #include <netinet/in.h>
  25. #include <netinet/in_systm.h>
  26. #include <netinet/ip.h>
  27. #include <netinet/udp.h>
  28. #include <netinet/tcp.h>
  29. #include <net/bpf.h>
  30.  
  31. #include "pcap-int.h"
  32.  
  33. static char     snoop_device[255];
  34. struct ifreq    ifr_orig;
  35.  
  36. void restore_interface(void);
  37.  
  38. void
  39. restore_interface()
  40. {
  41.     int             fd;
  42.  
  43.     fd = socket(PF_INET, SOCK_PACKET, htons(0x0003));
  44.     if (fd < 0) {
  45.     printf("Warning: could not restore interface to normal.\n");
  46.     return;
  47.     }
  48.     if (ioctl(fd, SIOCSIFFLAGS, &ifr_orig) < 0)
  49.     printf("Warning: could not restore interface to normal.\n");
  50. }
  51.  
  52. int
  53. pcap_read_live(pcap_t * p, int cnt, pcap_handler callback, u_char * user)
  54. {
  55.     register int    datalen;
  56.     register int    caplen;
  57.     struct sockaddr from;
  58.     int             from_len=sizeof(from);
  59.     char           *buf;
  60.     int             bufsize;
  61.  
  62.     if (p->linktype == DLT_SLIP) {
  63.     buf = (char *) p->buffer + 16;
  64.     bufsize = p->bufsize - 16;
  65.     memset(p->buffer, 0, 16);
  66. #ifdef LINUX_PPP_PATCH
  67.     } else if (p->linktype == DLT_PPP || p->linktype == DLT_NULL) {
  68.     buf = (char *) p->buffer + 4;
  69.     bufsize = p->bufsize - 4;
  70.     p->buffer[0] = 0x00;
  71.     p->buffer[1] = 0x00;
  72.     p->buffer[2] = 0x00;    /* hack: force IP protocol */
  73.     p->buffer[3] = 0x21;    /* kernel ppp.c should be fixed to 
  74.                     include protocol field */
  75. #endif
  76.     } else {
  77.     buf = (char *) p->buffer;
  78.     bufsize = p->bufsize;
  79.     }
  80.  
  81.     /* do until we find something from the right interface */
  82.     do {
  83.     datalen = recvfrom(p->fd, buf, bufsize, 0, &from, &from_len);
  84.  
  85.     if (datalen < 0) {
  86.         switch (errno) {
  87.         case EWOULDBLOCK:
  88.         return 0;
  89.         }
  90.         sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
  91.         return -1;
  92.     }
  93.     } while (strcmp(snoop_device, from.sa_data));    
  94.  
  95.     if (p->linktype == DLT_SLIP)
  96.     datalen += 16;
  97. #ifdef LINUX_PPP_PATCH
  98.     else if (p->linktype == DLT_PPP || p->linktype == DLT_NULL)
  99.     datalen += 4;
  100. #endif
  101.  
  102.     caplen = (datalen > p->bufsize) ? p->bufsize : datalen;
  103.  
  104.     if (caplen > p->snapshot)
  105.     caplen = p->snapshot;
  106.  
  107.     ++p->md.stat.ps_recv;
  108.  
  109.     if (p->fcode.bf_insns == NULL ||
  110.     bpf_filter(p->fcode.bf_insns, (char *) p->buffer, datalen, caplen)) {
  111.     struct pcap_hdr hdr;
  112.  
  113.     /* use gettimeofday if support for SIOCGSTAMP is missing or 
  114.        the request fails (it does in old kernel versions) */
  115. #ifdef SIOCGSTAMP
  116.     if (ioctl(p->fd, SIOCGSTAMP, &hdr.ts) < 0)    /* get the timestamp */
  117. #endif
  118.         gettimeofday(&hdr.ts, 0);    
  119.  
  120.     hdr.len = datalen;
  121.     hdr.caplen = caplen;
  122.     hdr.drops = 0;
  123.     (*callback) (user, &hdr, (char *) p->buffer);
  124.     return 1;
  125.     }
  126.     return 0;
  127. }
  128.  
  129. int
  130. pcap_stats_live(pcap_t * p, struct pcap_stat *ps)
  131. {
  132.     ps->ps_drop = 0;
  133.     ps->ps_recv = p->md.stat.ps_recv;
  134.     ps->ps_ifdrop = 0;
  135.     return 0;
  136. }
  137.  
  138. pcap_t *
  139. pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
  140. {
  141.     pcap_t         *p;
  142.     struct ifreq    ifr;
  143.     int has_promisc=0;
  144.  
  145.     p = (pcap_t *) malloc(sizeof(*p));
  146.     if (p == NULL) {
  147.     strcpy(ebuf, "no swap");
  148.     return 0;
  149.     }
  150.     bzero(p, sizeof(*p));
  151.     if (strncmp("et", device, 2) == 0) {
  152.     p->linktype = DLT_EN10MB;
  153.     has_promisc = 1;
  154.     }
  155.     else if (strncmp("sl", device, 2) == 0)
  156.     p->linktype = DLT_SLIP;
  157.     else if (strncmp("pp", device, 2) == 0)
  158.     p->linktype = DLT_PPP;
  159.     else if (strcmp("lo",device) == 0)
  160.     p->linktype = DLT_EN10MB;    /* Why on earth does linux do this? */
  161.     else {
  162.     sprintf(ebuf, "socket: unknown physical layer type");
  163.     goto bad;
  164.     }
  165.     p->fd = -1;
  166.     p->bufsize = 4096;
  167.     p->buffer = (u_char *) malloc(p->bufsize);
  168.     if (p->buffer == NULL) {
  169.     strcpy(ebuf, "no swap");
  170.     goto bad;
  171.     }
  172.     p->fd = socket(PF_INET, SOCK_PACKET, htons(0x0003));
  173.     if (p->fd < 0) {
  174.     sprintf(ebuf, "socket: %s", pcap_strerror(errno));
  175.     goto bad;
  176.     }
  177.     if (has_promisc && promisc) {
  178.     strcpy(ifr.ifr_name, device);    /* interface we're gonna use */
  179.     if (ioctl(p->fd, SIOCGIFFLAGS, &ifr) < 0) {    /* get flags */
  180.         sprintf(ebuf, "ioctl: %s", pcap_strerror(errno));
  181.         goto bad;
  182.     }
  183.     ifr_orig = ifr;
  184.     atexit(restore_interface);
  185.     ifr.ifr_flags |= IFF_PROMISC;    /* set promiscuous mode */
  186.  
  187.     if (ioctl(p->fd, SIOCSIFFLAGS, &ifr) < 0) {    /* set flags */
  188.         sprintf(ebuf, "ioctl: %s", pcap_strerror(errno));
  189.         goto bad;
  190.     }
  191.     }
  192.     strcpy(snoop_device, device);
  193.  
  194.     p->snapshot = snaplen;
  195.     return p;
  196.   bad:
  197.     if (p->fd >= 0)
  198.     close(p->fd);
  199.     if (p->buffer != NULL)
  200.     free(p->buffer);
  201.     free(p);
  202.     return 0;
  203. }
  204.  
  205. int
  206. pcap_setfilter_live(pcap_t * p, struct bpf_program *fp)
  207. {
  208.     p->fcode = *fp;
  209.     return 0;
  210. }
  211.